Salesforce Apex vs Synrc FormalTalk
[Biased] порівняльна характеристика Salesforce Apex та FormalTalk.
Мова для CRM/ERP системи
Якщо класифікувати FormalTalk, як мову згідно номенклатури, яка використовується в моій Енциклопедії Мов Програмування, то FormalTalk займає місце серед когорти мов які використовуються для промислових ERP систем. Візьме до прикладу Salesforce Apex (не путати з Oracle Apex, але якшо взяти і його, то нічого в статті не зміниться) і порівняємо її повністю імперативну мову Apex з вбудованою підмовою даних SOQL (щось подібне до LINQ).
Основне завдання цих недолугих мов, які не є мовами програмування загального призначення полягає в управлінні типовими специфікаціями та логікою складних продуктів з важкими рантаймами, а не для створення продуктів та їх лінковки в більш низькорівневій та загальній манері.
Salesfore Apex разом з вбудованим SOQL
Contact[] cc = [SELECT Id FROM Contact LIMIT 2];
Task[] tt = [SELECT Id FROM Task WHERE WhoId IN :cc];
String[] ss = new String[]{'a', 'b'};
Account[] aa = [SELECT Id FROM Account WHERE AccountNumber IN :ss];
String myString1 = 'aaa', myString2 = 'bbb', myString4 = 'ccc';
Integer myInt3 = 11, myInt5 = 22;
// A SOSL query with binds in all possible clauses
List> searchList = [FIND :myString1 IN ALL FIELDS RETURNING
Account (Id, Name WHERE Name LIKE :myString2 LIMIT :myInt3),
Contact, Opportunity, Lead WITH DIVISION =:myString4
LIMIT :myInt5];
При розробці FormalTalk враховувалась 10-річна практика програмування на бібліотеках N2O, яка формалізована у вигляді математичної моделі в System-F та MLTT як специфікація N2O.PRO. Оскільки N2O.PRO покриває модель Закмана, то і мова FormalTalk є своєрідним офіційним скриптом який розповсюджується на усі рівні ISO 42010.
Synrc FormalTalk ISO 42010 BPE
record routeProc
begin id = [] : list
| operation = [] : [] + atom
| feed = [] : [] + binary
| type = [] : atom
| folder = [] : binary
| users = [] : binary + list
| folderType = "personal" : binary
| callback = [] : [] + function
| reject = false : false + boolean
| options = [] : [] + list end
fun action request to=Archive
begin newDoc = proc.docs.hd | newProc = proc | newProc.docs = [newDoc]
| unindexUrgent proc newDoc | newState = actionGen req proc newProc
| result [ general req newState newDoc | stop ] newState reply proc.executors end
route routeTo
begin (Cr,R):R,[] | (R,gwND):O,R | (gwND,Det):D,[] | (*,InC):A,To
| (gwC,I):A,To,toExecutors | (*,G):G,[];P,M | (*,A):A,[] end
Відмінності між мовами
На відміну від Salesforce Apex, FormalTalk є декларативною мовою, що означає що ви кажете, що ви хочете дістати (навіть якщо це послідовність операцій), а не що робити в якій послідовності. Однак для практики, а саме для перепакування змінних та мінімального набору утилітарних фунцій роботи з записами, списками, словниками, мапами. Мова містить єдиний імперативний оператор присвоювання та обмежені можливості виклику функцій з повним контролем рекурсії.
Мотивація скриптових мов для облікових систем
Головна мотивація, якою користуються компанії при розробці таких мов програмування для масивних ран-таймів — це уніфікація інтерфейсів і повний контроль над усіма перетвореннями, які можуть знадобитися в подальшому (наприклад трансляція в інші мови), а також спосіб перебудовування графічного інтерфейсу та моделі даних системи в реальному часі, що є невід'ємною умовою на тендерах ERP/CRM систем, що було започатковано в таких система як BAAN.
Ці мови є недолугими тому, що вони є в сутності обгортками над реальною системою, і повинні бути зрозумілі операторам, бажано з примітивними синтаксиами. Але LISP та спеціалізовані мови погано продаються, тому будь-яка проста мова для працюючого продукту може виявитися більш ефективною ніж трата часу для пошуку найоптимальнішої мови чи робота у її відсутності.
Контроль над подальшими транформаціями з мови FormalTalk у формальні лямюда мови як System F або фібраційні мови CoC або MLTT, а також обмеження та контроль рекурсії та всіх викливів є такою однією з головних технічних мотивацій, що призведе до драматичного усунення помилок при програмуванні логіки. Перше — транформації — є тим, що відкриває ворота для матаметатичної верифікації декларативної логіки яка записана на мові FormalTalk. Друге — контрольовані виклики та рекурсія — є тим, що дозволяє більш безпосередньо транслювати програми у формальні фібраційні мови.
Мова для веб-фреймворку
Мова FormalTalk може бути одночасно прокласифікована як спеціалізована мова для побудови сайтів, тобто DSL для веб-фреймворка зі своїм лексером та парсером, у цьому сенсі її можна порівняти з UrWeb.
UrWeb
let main () =
let
fun create r =
id <- nextval s;
room <- Room.create;
dml (INSERT INTO t (Id, Title, Room) VALUES ({[id]}, {[r.Title]}, {[room]}));
main ()
end
У попередній статті ми розказали про BPE, FORM, KVS підмови FormalTalk, а тут покажемо як виглядає класичний приклад N2O.SAMPLE на мові FormalTalk
Synrc FormalTalk ISO 42010 NITRO
module Sample.Index nitro
fun room []:list begin ret '/root' end
fun room []:binary begin ret '/root' end
fun room begin end
fun chat message
begin nx = n2o:session :room
| room = call room nx
| user = n2o:user
| x = kvs:writer room
| y = KVS.writer{args={:msg,kvs:seq,user:var,message:var}}
| z = kvs:add y
| w = kvs:save z
| n2o:send {:topic,room} N2O.client{data={user,message}} end
fun display {:msg,_,user:var,message:var}
begin nitro:wire NITRO.jq{target=:message,method=[:focus,:select]}
| jse = nitro:jse message
| nitro:insert_top :history NITRO.message{body=[NITRO.author{body=user:var},jse]} end
fun event :logout begin n2o:user [] | nitro:redirect "/app/login.htm" end
fun event :chat begin message = nitro:q :message | call chat message end
fun event {:client,{user,message}} begin call display {:msg,user,message} end
fun event :init
begin nx = n2o:session :room
| room:var = call room nx
| kvs:ensure KVS.writer{id=room}
| n2o:subscribe {:topic,room}
| n2o:subscribe {n2o.sid}
| nitro:update :upload NITRO.upload
| nitro:update :heading NITRO.h2{id=:heading,body=room}
| nitro:update :logout NITRO.button{id=:logout,body="Logout",postback=:logout}
| nitro:update :send NITRO.butto{id=:send,body="Chat",postback=:chat,source=[:message]}
| messages = kvs:all room
| lists:map messages display end